"""
utils.decorators

Decorate your code!
"""

the_cache = {}

def cache(by_num, by_name):
    """
    Caches a function's return value depending on the arguments.
    
    Yes this looks insane and one could write it nicer, but hey, it works!
    """
    def decorator(func):
        the_cache[func] = {}
        def decorated(*args, **kwargs):
            try:
                by_arg = args[by_num]
            except:
                by_arg = kwargs[by_name]
            thiscache = the_cache[func]
            if by_arg in thiscache:
                return thiscache[by_arg]
            else:
                return_value = func(*args, **kwargs)
                thiscache[by_arg] = return_value
                return return_value
        return decorated
    return decorator